Final Post: 2024 Presidential Forecast

Alex Heuss

2024/11/03

Introductory Note

Over the course of nine weeks, we’ve explored the power of the economy, incumbency, polling, demographics, and certain campaign data in predicting election outcomes. For the past several weeks, my model has predicted the same outcome: Harris wins Wisconsin, Michigan and Pennsylvania, while Trump takes the rest. My national popular vote prediction has steadily narrowed, with Trump now within a percentage point of Harris. If anything has become clear to me over the course of this process, it is that this race is truly a coin flip. I’m excited to see how my predictions fare.

Model Breakdown

In forecasting the 2024 Presidential Election, I created two separate models, one to forecast the national popular vote and another to predict the electoral college. Both of my forecasts rely primarily on fundamentals, polling and lagged vote share. My models also include measures of “partisan swing,” which measures the change in partisan identification for a party between 2024 and either the year prior or the election prior, and is motivated by an underlying theory of increasing partisanship and polarization in the electorate.

My national popular vote prediction model uses LASSO to select the most influential predictors from a lengthy list of options including: incumbency measures, June presidential approval rating, percent of the country identifying as Democrat, Republican or Independent, and how those numbers changed from both the previous year and the prior election, lagged vote share, weekly polling averages in the 30 weeks leading up to the election, and economic measures of GDP, RDPI and stock prices.

\[model formula\]
## 56 x 1 sparse Matrix of class "dgCMatrix"
##                            s0
## (Intercept)       12.16385198
## party              .         
## incumbent          .         
## incumbent_party    .         
## prev_admin         .         
## deminc             .         
## juneapp            .         
## percent            .         
## two_party_percent  .         
## ind_percent       -0.03353438
## year_prior         .         
## year_prior_2p      .         
## swing1             0.10886823
## swing1_2p          .         
## prior_election     .         
## prior_election_2p  .         
## swing4             .         
## swing4_2p          .         
## pv_lag1            0.07203991
## pv_lag2            .         
## nat_weeks_left_1   0.27451795
## nat_weeks_left_2   .         
## nat_weeks_left_3   .         
## nat_weeks_left_4   .         
## nat_weeks_left_5   0.16824573
## nat_weeks_left_6   .         
## nat_weeks_left_7   .         
## nat_weeks_left_8   .         
## nat_weeks_left_9   .         
## nat_weeks_left_10  .         
## nat_weeks_left_11  0.04043554
## nat_weeks_left_12  .         
## nat_weeks_left_13  .         
## nat_weeks_left_14  .         
## nat_weeks_left_15  .         
## nat_weeks_left_16  .         
## nat_weeks_left_17  0.01569250
## nat_weeks_left_18  0.24508926
## nat_weeks_left_19  .         
## nat_weeks_left_20  .         
## nat_weeks_left_21  .         
## nat_weeks_left_22  .         
## nat_weeks_left_23  .         
## nat_weeks_left_24  .         
## nat_weeks_left_25  .         
## nat_weeks_left_26  .         
## nat_weeks_left_27  .         
## nat_weeks_left_28  .         
## nat_weeks_left_29  .         
## nat_weeks_left_30  .         
## q2_gdp_growth      .         
## q2_rdpi_growth     .         
## GDP                .         
## RDPI               .         
## nat_unemployment   .         
## stock_adj_close    .

My LASSO model selected 8 predictors as important in reducing the error of my model: percent of the country identifying as independent, the change in party identification for either party from the year preceding the election, vote share from the previous election, and five different weeks of polling, including the week just prior to the election. The cross-validated R-squared value for my model is 0.88. Polling data and partisan swing have the largest coefficient sizes. An example interpretation of one of the coefficients would be: for each increase of one percentage point in a party’s identification from the year prior to the election to election year, that party’s candidate’s vote share increases by 0.1 percentage points. On the surface, that may not seem like a lot, but several “small” coefficient predictors add up.

Electoral College Vote

My electoral college model takes in less predictive variables. I make two separate models for predicting the electoral college, one for states with significant polling aggregate data on FiveThirtyEight, and one for those without. Predictive variables for both models include: state-level lagged vote share for the two prior elections, whether the candidate is a member of the incumbent party, national quarter 2 GDP growth, average state-level unemployment, the change in partisan identification for either party from the last election, and state fixed effects. For states with polling aggregates, the mean polling average and latest polling average are included in my model.

\[model formula\]
##        1        2        3        4        5        6        7        8 
## 48.33354 60.93116 45.60991 48.31099 64.08853 63.95883 51.19725 52.30443 
##        9       10       11       12       13       14       15       16 
## 43.23846 39.03317 38.00009 48.99651 51.48999 52.59473 56.64457 47.03191 
##       17       18       19       20       21       22       23       24 
## 44.79904 50.16141 44.97342 51.93869 57.72301 50.57118 55.67006 56.60709

##        pred      lwr      upr
## 1  48.33354 44.58212 52.08497
## 2  60.93116 57.17974 64.68259
## 3  45.60991 41.85848 49.36133
## 4  48.31099 44.55956 52.06241
## 5  64.08853 60.33711 67.83996
## 6  63.95883 60.20741 67.71026
## 7  51.19725 47.44582 54.94867
## 8  52.30443 48.55300 56.05585
## 9  43.23846 39.48704 46.98989
## 10 39.03317 35.28175 42.78460
## 11 38.00009 34.24866 41.75151
## 12 48.99651 45.24509 52.74794
## 13 51.48999 47.73857 55.24141
## 14 52.59473 48.84331 56.34616
## 15 56.64457 52.89315 60.39600
## 16 47.03191 43.28049 50.78334
## 17 44.79904 41.04761 48.55046
## 18 50.16141 46.40999 53.91283
## 19 44.97342 41.22200 48.72485
## 20 51.93869 48.18726 55.69011
## 21 57.72301 53.97159 61.47444
## 22 50.57118 46.81976 54.32261
## 23 55.67006 51.91864 59.42149
## 24 56.60709 52.85566 60.35851

##        pred      lwr      upr
## 1  34.46671 25.22258 43.71084
## 2  39.82749 30.58336 49.07162
## 3  35.23750 25.99336 44.48163
## 4  55.43944 46.19531 64.68357
## 5  54.99127 45.74713 64.23540
## 6  59.08096 49.83683 68.32509
## 7  28.24052 18.99639 37.48465
## 8  54.80184 45.55771 64.04597
## 9  38.57506 29.33093 47.81919
## 10 42.23918 32.99505 51.48331
## 11 37.95750 28.71337 47.20163
## 12 32.25060 23.00647 41.49473
## 13 39.07137 29.82724 48.31550
## 14 39.47930 30.23517 48.72343
## 15 53.94440 44.70027 63.18853
## 16 26.84904 17.60491 36.09317
## 17 29.54936 20.30523 38.79349
## 18 51.87926 42.63513 61.12339
## 19 57.39381 48.14968 66.63794
## 20 40.90441 31.66028 50.14854
## 21 28.61306 19.36893 37.85719
## 22 36.37055 27.12642 45.61468
## 23 32.53530 23.29117 41.77943
## 24 58.82200 49.57787 68.06613
## 25 30.49181 21.24768 39.73595
## 26 24.36947 15.12533 33.61360

## 
## Call:
## lm(formula = .outcome ~ ., data = dat)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.6864 -0.9452  0.0075  1.0198  6.2622 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             8.490611   1.639295   5.179 6.01e-07 ***
## latest_pollav_DEM       0.636025   0.050577  12.575  < 2e-16 ***
## mean_pollav_DEM         0.063184   0.044010   1.436 0.152856    
## D_pv_lag1               0.172542   0.033103   5.212 5.16e-07 ***
## D_pv_lag2              -0.037803   0.025319  -1.493 0.137202    
## incumbent_partyTRUE     0.249170   0.345263   0.722 0.471443    
## q2_gdp_growth           0.022438   0.015765   1.423 0.156407    
## avg_state_unemployment  0.107177   0.098937   1.083 0.280153    
## dem_perc_swing         -0.006054   0.013972  -0.433 0.665316    
## rep_perc_swing         -0.006430   0.015751  -0.408 0.683592    
## stateCalifornia         2.116318   1.055291   2.005 0.046440 *  
## stateColorado           0.350983   0.995406   0.353 0.724806    
## stateFlorida           -0.916874   1.002994  -0.914 0.361888    
## stateGeorgia           -0.183100   1.015898  -0.180 0.857175    
## stateMaine              0.015522   1.391019   0.011 0.991109    
## stateMaryland           2.896403   1.092723   2.651 0.008763 ** 
## stateMassachusetts      3.919226   1.091799   3.590 0.000429 ***
## stateMichigan           1.912411   1.052550   1.817 0.070919 .  
## stateMinnesota          1.204050   1.037450   1.161 0.247373    
## stateMissouri          -0.536897   1.035603  -0.518 0.604800    
## stateMontana           -2.704191   1.609727  -1.680 0.094740 .  
## stateNebraska          -3.878691   1.212902  -3.198 0.001640 ** 
## stateNevada             0.136722   1.312436   0.104 0.917149    
## `stateNew Hampshire`    0.192059   1.092616   0.176 0.860668    
## `stateNew Mexico`       1.043815   1.297480   0.804 0.422191    
## `stateNew York`         1.510022   1.064815   1.418 0.157918    
## `stateNorth Carolina`  -1.280866   1.035287  -1.237 0.217649    
## stateOhio              -0.673344   1.007398  -0.668 0.504749    
## statePennsylvania       1.157246   1.023277   1.131 0.259618    
## stateTexas             -0.757347   0.992960  -0.763 0.446647    
## stateVirginia           0.854729   0.999525   0.855 0.393632    
## stateWashington         1.519807   1.024802   1.483 0.139846    
## stateWisconsin          1.406889   1.020135   1.379 0.169598    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.914 on 177 degrees of freedom
## Multiple R-squared:  0.936,	Adjusted R-squared:  0.9244 
## F-statistic: 80.86 on 32 and 177 DF,  p-value: < 2.2e-16

## 
## Call:
## lm(formula = .outcome ~ ., data = dat)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -8.826 -2.525  0.079  2.566  9.982 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            13.584297   4.080296   3.329  0.00114 ** 
## D_pv_lag1               0.571003   0.070990   8.043  5.1e-13 ***
## D_pv_lag2               0.097555   0.064725   1.507  0.13422    
## incumbent_partyTRUE    -2.563009   0.957730  -2.676  0.00842 ** 
## q2_gdp_growth          -0.027435   0.038468  -0.713  0.47703    
## avg_state_unemployment -0.030232   0.270109  -0.112  0.91106    
## dem_perc_swing          0.004528   0.027651   0.164  0.87019    
## rep_perc_swing         -0.037591   0.031593  -1.190  0.23631    
## stateAlaska             1.341766   3.674850   0.365  0.71562    
## stateArkansas           1.928218   2.240047   0.861  0.39096    
## stateConnecticut        5.612684   2.199396   2.552  0.01189 *  
## stateDelaware           5.855018   4.019572   1.457  0.14767    
## stateHawaii             5.296471   4.428031   1.196  0.23386    
## stateIdaho             -2.990001   3.829487  -0.781  0.43637    
## stateIllinois           5.937094   2.197593   2.702  0.00784 ** 
## stateIndiana            1.359286   2.087961   0.651  0.51621    
## stateIowa               2.425217   2.302244   1.053  0.29414    
## stateKansas             0.558267   2.284349   0.244  0.80732    
## stateKentucky          -1.752716   3.708228  -0.473  0.63726    
## stateLouisiana          1.805360   2.217026   0.814  0.41698    
## stateMississippi        1.623151   2.956515   0.549  0.58396    
## `stateNew Jersey`       5.239889   2.139260   2.449  0.01566 *  
## `stateNorth Dakota`    -4.363556   3.252359  -1.342  0.18208    
## stateOklahoma          -1.981762   2.699730  -0.734  0.46426    
## stateOregon             4.564242   2.104922   2.168  0.03198 *  
## `stateRhode Island`     6.972337   3.552869   1.962  0.05188 .  
## `stateSouth Carolina`   2.140027   2.634950   0.812  0.41820    
## `stateSouth Dakota`    -3.826466   3.372609  -1.135  0.25868    
## stateTennessee          1.360200   2.093539   0.650  0.51704    
## stateUtah              -2.104533   3.056566  -0.689  0.49237    
## stateVermont            6.587487   4.348919   1.515  0.13230    
## `stateWest Virginia`    0.815409   2.297063   0.355  0.72319    
## stateWyoming           -1.648196   2.570163  -0.641  0.52249    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.716 on 128 degrees of freedom
## Multiple R-squared:  0.7859,	Adjusted R-squared:  0.7324 
## F-statistic: 14.68 on 32 and 128 DF,  p-value: < 2.2e-16

For my model with polls, the latest poll average holds significant predictive weight, as does a state’s most recent presidential election vote share. On the other hand, lagged vote share is the most important for state’s without polls, followed by incumbency. We see also in both models that state fixed effects can have very large coefficients and thus may have large predictive power, despite being less significant than other variables. My models with polls has a 0.91 cross-validated r-squared, however my model without polls only has an r-squared of 0.66. Luckily, the states without polls are not close in this election, so the precise vote share prediction is not as important as in swing states.

Predictions

Candidate Predicted Vote Share Lower Bound Upper Bound
Harris 49.02198 46.90672 51.13725
Trump 48.08504 46.57114 49.59895

Electoral College

All in all, my model predicts that Harris will win the electoral college, 270-268 - an insanely tight margin.

Winner States Won Electors
Democrat 23 270
Republican 28 268

The following graph presents the breakdown for my swing state predictions including confidence intervals.

State Harris Prediction Lower Upper Margin Winner
Michigan 51.19725 47.44582 54.94867 2.3944945 Democrat
Pennsylvania 50.16141 46.40999 53.91283 0.3228206 Democrat
Wisconsin 50.57118 46.81976 54.32261 1.1423643 Democrat
Arizona 48.33354 44.58212 52.08497 -3.3329166 Republican
Georgia 48.31099 44.55956 52.06241 -3.3780227 Republican
Nevada 48.99651 45.24509 52.74794 -2.0069705 Republican
North Carolina 47.03191 43.28049 50.78334 -5.9361700 Republican

(#tab:swing state specific breakdown)Swing State Prediction Breakdown

In a race as tight as 2024, it is nearly impossible to predict tight swing states and have a confidence interval that puts one candidate as a clear winner, and my predictions are no exception.

Below is the map of all my electoral college predictions and their associated vote share margins. Negative vote shares represent Trump wins and positive values represent Harris wins.

## Reading layer `states' from data source 
##   `C:\Users\aheus\Desktop\r_files\election_analytics\election-blog2\content\post\2024-11-03-final-post-2024-presidential-forecast\data\states.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 56 features and 9 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -10428900 ymin: -1697746 xmax: 3407823 ymax: 5140484
## Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic